package com.hqm.auth.controller;


import com.hqm.auth.request.LoginRequest;
import com.hqm.auth.request.RefreshRequest;
import com.hqm.auth.response.LoginResponse;
import com.hqm.auth.response.ResponseCodeEnum;
import com.hqm.auth.util.JWTUtil;
import com.hqm.common.exception.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author: qzuser
 * @date: 2022/3/30 19:48
 * @description:
 */
@RestController
@RequestMapping("/auth")
public class LoginController {

    @Value("${secretKey:123456}")
    private String secretKey;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    final static String TOKEN = "token";

    final static String REFRESH_TOKEN = "refreshToken";

    @PostMapping("/login/")
    public Result login(@RequestBody @Validated LoginRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return Result.error(ResponseCodeEnum.PARAMETER_ILLEGAL.getCode(), ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
        }

        String username = request.getUsername();
        String password = request.getPassword();
        //  假设查询到用户ID是1001
        String userId = "1001";
        //相当于调用后台数据库，判断用户是否存在
        if ("tom".equals(username) && "123456".equals(password)) {
            //  生成Token
            String token = JWTUtil.generateToken(userId,username,secretKey);

            //  生成刷新Token
            String refreshToken = UUID.randomUUID().toString().replace("-", "");

            //  放入缓存
            HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();

            String key = userId;
            hashOperations.put(key, TOKEN, token);
            hashOperations.put(key, REFRESH_TOKEN, refreshToken);
            stringRedisTemplate.expire(key, JWTUtil.TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);

            LoginResponse loginResponse = new LoginResponse();
            loginResponse.setToken(token);
            loginResponse.setRefreshToken(refreshToken);
            loginResponse.setUserId(userId);
            loginResponse.setUsername(username);

            return Result.ok().data("loginResponse",loginResponse);
        }

        return Result.error(ResponseCodeEnum.LOGIN_ERROR.getCode(), ResponseCodeEnum.LOGIN_ERROR.getMessage());
    }

    @GetMapping("/logout")
    public Result logout(@RequestParam("userId") String userId) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        String key = userId;
        hashOperations.delete(key, TOKEN);
        return Result.ok();
    }

    @PostMapping("/refreshToken")
    public Result refreshToken(@RequestBody @Validated RefreshRequest request, BindingResult bindingResult) {
        String userId = request.getUserId();
        //通过userId去数据库查到userName
        String userName="tom";
        String refreshToken = request.getRefreshToken();
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        String key = userId;
        String originalRefreshToken = hashOperations.get(key, REFRESH_TOKEN);
        if (StringUtils.isBlank(originalRefreshToken) || !originalRefreshToken.equals(refreshToken)) {
            return Result.error(ResponseCodeEnum.REFRESH_TOKEN_INVALID.getCode(), ResponseCodeEnum.REFRESH_TOKEN_INVALID.getMessage());
        }

        //  生成新token
        String newToken = JWTUtil.generateToken(userId,userName,secretKey);
        hashOperations.put(key, TOKEN, newToken);
        stringRedisTemplate.expire(userId, JWTUtil.TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);

        return Result.ok(newToken);
    }
}
